package com.hfzy.ihk.web.calldata.serviceImpl;



import com.alibaba.fastjson.JSON;
import com.hfzy.ihk.common.constants.GlobalStatic;
import com.hfzy.ihk.common.core.elasticsearch.ElasticsearchLocalCache;
import com.hfzy.ihk.common.core.elasticsearch.ElasticsearchOperation;
import com.hfzy.ihk.common.util.CommonUtils;
import com.hfzy.ihk.common.util.string.StringTools;
import com.hfzy.ihk.common.web.WebResult;
import com.hfzy.ihk.facade.calldata.entity.CallHistory;
import com.hfzy.ihk.facade.calldata.entity.CallHistoryText;
import com.hfzy.ihk.facade.calldata.entity.CallTaskDetail;
import com.hfzy.ihk.facade.calldata.enums.CallDataOperations;
import com.hfzy.ihk.facade.calldata.enums.CallDataTables;
import com.hfzy.ihk.facade.calldata.service.EsOptRmiService;
import com.hfzy.ihk.web.calldata.biz.CallHistoryBiz;
import com.hfzy.ihk.web.calldata.biz.CallHistoryTextBiz;
import com.hfzy.ihk.web.calldata.biz.CallTaskDetailBiz;
import com.hfzy.ihk.web.calldata.constant.RedisKey;
import com.hfzy.ihk.web.calldata.handlers.CallHistoryTableOperationHandler;
import com.hfzy.ihk.web.calldata.handlers.CallHistoryTextTableOperationHandler;
import com.hfzy.ihk.web.calldata.vo.CallTaskDetailTotalVo;
import org.elasticsearch.common.UUIDs;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.util.*;

/**
 * Created by Administrator on 2018/8/14.
 */
//@Service(version = "1.0.0")
@Service
public class EsOptRmiServiceImpl implements EsOptRmiService {

    private static final Logger logger = LoggerFactory.getLogger(EsOptRmiServiceImpl.class);

    @Autowired
    CallHistoryBiz callHistoryBiz;

    @Autowired
    CallHistoryTextBiz callHistoryTextBiz;

    @Autowired
    CallTaskDetailBiz callTaskDetailBiz;

    @Autowired
    CallHistoryTableOperationHandler callHistoryTableOperationHandler;

    @Autowired
    CallHistoryTextTableOperationHandler callHistoryTextTableOperationHandler;

    @Resource
    TaskExecutor callTaskExecutor;

    @Autowired
    RedisTemplate redisTemplate;


    /**
     * 保存或修改呼叫记录
     * @param jsonStr
     * @return
     */
    @Override
    public String createOrUpdateCloudCallHistoryBySessionId(String jsonStr) {
        if(StringTools.isNotempty(jsonStr)){
            logger.info(jsonStr);
            Map<String,Object> paramMap = JSON.toJavaObject(JSON.parseObject(jsonStr),Map.class);
            if(!paramMap.containsKey("sessionId")){
                logger.error("createOrUpdateCloudCallHistoryBySessionId方法sessionId不能为空！");
                return "0";
            }
            /*if(!paramMap.containsKey("recordFileUrl")&&!paramMap.containsKey("customerFollowCategory")){
                if(!paramMap.containsKey("callTaskId")){
                    logger.error("createOrUpdateCloudCallHistoryBySessionId方法callTaskId不能为空！");
                    return "0";
                }
            }*/
            try {
                callTaskExecutor.execute(()->{
                    try {
                        CallHistory callHistory = callHistoryBiz.selectById(paramMap.get("sessionId").toString());
                        CallHistory oldCallHistory = null;
                        if(callHistory == null){//不存在就是新增
                            callHistory = new CallHistory();
                            callHistory.setVersion(1L);
                        }else{//存在就是修改，然后把旧对象存起来
                            oldCallHistory = new CallHistory();
                            BeanUtils.copyProperties(callHistory,oldCallHistory);
                        }
                        //把修改的数据set进去
                        for(String key : paramMap.keySet()){
                            if("version".equals(key)||StringTools.isEmpty(paramMap.get(key))||"null".equals(paramMap.get(key))){
                                continue;
                            }
                            if("mainCallLength".equals(key)){//主叫通话时长
                                Integer mainCallLength = Integer.valueOf(paramMap.get(key).toString());
                                callHistory.setMainChargingLength((int)Math.ceil((double) mainCallLength/60));
                            }
                            if("targetCallLength".equals(key)){//被叫通话时长
                                Integer targetCallLength = Integer.valueOf(paramMap.get(key).toString());
                                callHistory.setTargetChargingLength((int)Math.ceil((double) targetCallLength/60));
                            }
                            try {
                                CommonUtils.setObjName(callHistory,key,paramMap.get(key));
                            } catch (Exception e) {
                                logger.error("保存或修改呼叫记录反射字段出错，name:{},value:{},异常信息:{}",key,paramMap.get(key),e);
                                continue;
                            }
                        }
                        //总计费时长
                        Integer totalBillingLength = 0;
                        if(StringTools.isNotempty(callHistory.getMainChargingLength())){
                            totalBillingLength += callHistory.getMainChargingLength();
                        }
                        if(StringTools.isNotempty(callHistory.getTargetChargingLength())){
                            totalBillingLength += callHistory.getTargetChargingLength();
                        }
                        callHistory.setTotalBillingLength(totalBillingLength);

                        WebResult result = new WebResult();

                        Map<String,Object> redisMap = new HashMap<>();

                        if(oldCallHistory == null){//新增
                            /*判断通话状态用于统计*/
                            if(paramMap.containsKey("commitTo")){
                                if("8".equals(paramMap.get("commitTo").toString())&&paramMap.containsKey("targetCallAnswered")&&Boolean.valueOf(paramMap.get("targetCallAnswered").toString())){
                                    callHistory.setHasState(true);
                                    redisMap.put("callState",true);
                                }else{
                                    if(paramMap.containsKey("mainCallAnswered")&&Boolean.valueOf(paramMap.get("mainCallAnswered").toString())){
                                        callHistory.setHasState(true);
                                        redisMap.put("callState",true);
                                    }
                                }
                            }else{
                                if(paramMap.containsKey("roundTimes")&&Integer.valueOf(paramMap.get("roundTimes").toString())>0){
                                    callHistory.setHasState(true);
                                    redisMap.put("callState",true);
                                }
                            }

                            result = callHistoryBiz.saveCallHistory(callHistory);

                            if(GlobalStatic.CODE_1.equals(result.getCode())&&paramMap.containsKey("callTaskId")){
                                Map createMap = CommonUtils.objectMap(callHistory,null,Arrays.asList(
                                        "callTaskId","sessionId","mainCallRinging","recordTimeLength",
                                        "roundTimes","customerNeedLevel","focusWords"
                                ),false);
                                redisMap.putAll(createMap);
                                //用来确保接通次数不会出错
                                /*if(!redisMap.containsKey("mainCallAnswered")){
                                    redisMap.put("mainCallAnswered",true);
                                }*/
                            }
                        }else {//修改
                            Map<String,Object> updateMap =  CommonUtils.compareObj(oldCallHistory,callHistory,
                                    Arrays.asList("serialVersionUID","sessionId","version"),null);
                            if(!updateMap.isEmpty()){
                                /*判断通话状态用于统计*/
                                if(!oldCallHistory.getHasState()){
                                    if(paramMap.containsKey("commitTo")){
                                        if("8".equals(paramMap.get("commitTo").toString())&&paramMap.containsKey("targetCallAnswered")&&Boolean.valueOf(paramMap.get("targetCallAnswered").toString())){
                                            updateMap.put("hasState",true);
                                            redisMap.put("callState",true);
                                        }else{
                                            if(paramMap.containsKey("mainCallAnswered")&&Boolean.valueOf(paramMap.get("mainCallAnswered").toString())){
                                                updateMap.put("hasState",true);
                                                redisMap.put("callState",true);
                                            }
                                        }
                                    }else{
                                        if(paramMap.containsKey("roundTimes")&&Integer.valueOf(paramMap.get("roundTimes").toString())>0){
                                            updateMap.put("hasState",true);
                                            redisMap.put("callState",true);
                                        }
                                    }
                                }

                                result = callHistoryBiz.updateCallHistory(updateMap,paramMap.get("sessionId").toString(),oldCallHistory.getVersion());
                                if(GlobalStatic.CODE_1.equals(result.getCode())&&paramMap.containsKey("callTaskId")){
                                    redisMap.putAll(updateMap);
                                    redisMap.put("callTaskId",paramMap.get("callTaskId").toString());
                                    //用来确保接通次数不会出错
                                    /*if(redisMap.containsKey("mainCallAnswered")){
                                        redisMap.remove("mainCallAnswered");
                                    }*/
                                    if(redisMap.containsKey("version")){
                                        redisMap.remove("version");
                                    }
                                }
                            }
                        }
                        if(GlobalStatic.CODE_N.equals(result.getCode())){
                            throw new RuntimeException();
                        }else if(GlobalStatic.CODE_1.equals(result.getCode())){
                            //统计存入缓存
                            try {
                                if(!redisMap.isEmpty()){
                                    //修改录音地址和人工分类不用统计
                                    if(redisMap.containsKey("callTaskId")&&StringTools.isNotempty(redisMap.get("callTaskId"))){
                                        callTaskDetailBiz.queueStatisticsCallHistory(redisMap);
                                    }else{
                                        logger.error("通话详情统计放入redis出错,没有callTaskId或者为空,sessionId:{}",callHistory.getSessionId());
                                    }
                                    //callTaskDetailBiz.statisticsCallHistory(redisMap);
                                }
                            }catch (Exception e){
                                logger.error("通话详情统计放入redis出错，错误信息error:{}，data:{}",e,JSON.toJSON(redisMap));
                                ElasticsearchLocalCache.put(redisMap);
                            }
                        }
                    }catch (Exception e){
                        logger.error("保存通话记录异常sessionId:{},错误信息error:{}",paramMap.get("sessionId"),e);
                        ElasticsearchOperation operation = new ElasticsearchOperation(paramMap.get("sessionId").toString(),
                                CallDataTables.CALL_HISTORY.getTableName(),
                                CallDataOperations.addCallHistory.getOperationName(),
                                JSON.parseObject(jsonStr));
                        callHistoryTableOperationHandler.handleError(operation,e);
                    }
                });
            }catch (Exception e){
                logger.error("保存通话记录线程异常：{}",e);
                ElasticsearchOperation operation = new ElasticsearchOperation(paramMap.get("sessionId").toString(),
                        CallDataTables.CALL_HISTORY.getTableName(),
                        CallDataOperations.addCallHistory.getOperationName(),
                        JSON.parseObject(jsonStr));
                callHistoryTableOperationHandler.handleError(operation,e);
            }
        }
        return "1";
    }

    /**
     * 保存通话内容
     * @param jsonStr
     * @return
     */
    @Override
    public String createCallHistoryTextById(String jsonStr){
        if(StringTools.isNotempty(jsonStr)){
            logger.info("createCallHistoryTextById方法开始data:{}",jsonStr);

            Map<String,Object> paramMap = JSON.toJavaObject(JSON.parseObject(jsonStr),Map.class);
            if(!paramMap.containsKey("sessionId")){
                logger.error("createCallHistoryTextById方法sessionId不能为空!data:{}",jsonStr);
                return "0";
            }
            if(!paramMap.containsKey("callTaskId")){
                logger.error("createOrUpdateCloudCallHistoryBySessionId方法callTaskId不能为空！");
                return "0";
            }

            try {
                callTaskExecutor.execute(()->{
                    try{
                        CallHistoryText callHistoryText = new CallHistoryText();
                        for(String key : paramMap.keySet()){
                            try {
                                CommonUtils.setObjName(callHistoryText,key,paramMap.get(key));
                            } catch (Exception e) {
                                continue;
                            }
                        }

                        callHistoryText.setId(UUIDs.base64UUID());
                        callHistoryText.setCreateTime(new Date());
                        callHistoryText.setVersion(1);
                        logger.info(JSON.toJSONString(callHistoryText));
                        WebResult result = callHistoryTextBiz.saveCallHistoryText(callHistoryText);
                        if(GlobalStatic.CODE_N.equals(result.getCode())){
                            throw new RuntimeException();
                        }
                    }catch (Exception e){
                        logger.error("保存通话内容异常sessionId:{},错误信息error:{}",paramMap.get("sessionId"),e);
                        ElasticsearchOperation operation = new ElasticsearchOperation(paramMap.get("sessionId").toString(),
                                CallDataTables.CALL_HISTORY_TEXT.getTableName(),
                                CallDataOperations.addCallHistoryText.getOperationName(),
                                JSON.parseObject(jsonStr));
                        callHistoryTextTableOperationHandler.handleError(operation,e);
                    }
                });
            }catch (Exception e){
                logger.error("保存通话内容异常,错误信息error:{}",e);
                ElasticsearchOperation operation = new ElasticsearchOperation(paramMap.get("sessionId").toString(),
                        CallDataTables.CALL_HISTORY_TEXT.getTableName(),
                        CallDataOperations.addCallHistoryText.getOperationName(),
                        JSON.parseObject(jsonStr));
                callHistoryTextTableOperationHandler.handleError(operation,e);
            }
        }
        return "1";
    }

    /**
     * 获取通话记录接口
     * @param paramMap
     * @return
     */
    @Override
    public Map<String,Object> queryCallHistoryList(Map<String,Object> paramMap){
        Map<String,Object> resultMap = new HashMap<>();
        try {
            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            if(paramMap.containsKey("callTaskId")){
                builder.must(QueryBuilders.termQuery("callTaskId",paramMap.get("callTaskId").toString()));
            }
            if(paramMap.containsKey("sessionId")){
                builder.must(QueryBuilders.termQuery("sessionId.keyword",paramMap.get("sessionId").toString()));
            }

            //额外添加参数
            //分页
            Pageable pageable=null;
            if(paramMap.containsKey("page")&&paramMap.containsKey("limit")){

                 pageable = PageRequest.of(Integer.parseInt(paramMap.get("page").toString())-1, Integer.parseInt(paramMap.get("limit").toString()));
            }
            //排序
            FieldSortBuilder order=null;
            if(paramMap.containsKey("sort")){

                //降序
                if(((String)paramMap.get("sort")).equals("desc")){

                    order = SortBuilders.fieldSort("mainCallStartTime").order(SortOrder.DESC);
                }else{

                    //升序
                    order= SortBuilders.fieldSort("mainCallStartTime").order(SortOrder.ASC);
                }
            }


            Page<CallHistory> page = callHistoryBiz.queryCallHistoryPageList(builder,order,pageable,null);
            resultMap.put("msg","成功");
            resultMap.put("result",10000);
            resultMap.put("data",JSON.toJSONString(page));
            return resultMap;
        }catch (Exception e){
            logger.error("分页获取通话记录查询出错! data:{},错误信息:{}",paramMap,e);
            e.printStackTrace();
            resultMap.put("msg","失败");
            resultMap.put("result",10001);
        }
        return resultMap;
    }

    /**
     * 获取通话记录接口
     * @param paramMap
     * @return
     */
    @Override
    public Map<String,Object> queryCallHistoryTextList(Map<String,Object> paramMap){
        Map<String,Object> resultMap = new HashMap<>();
        try {
            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            if(paramMap.containsKey("callTaskId")){
                builder.must(QueryBuilders.termQuery("callTaskId",paramMap.get("callTaskId").toString()));
            }
            if(paramMap.containsKey("sessionId")){
                builder.must(QueryBuilders.termQuery("sessionId",paramMap.get("sessionId").toString()));
            }

            //额外添加参数
            //分页
            Pageable pageable=null;
            if(paramMap.containsKey("page")&&paramMap.containsKey("limit")){

                pageable = PageRequest.of(Integer.parseInt(paramMap.get("page").toString())-1, Integer.parseInt(paramMap.get("limit").toString()));
            }
            //排序
            FieldSortBuilder order=null;
            if(paramMap.containsKey("sort")){

                //降序
                if(((String)paramMap.get("sort")).equals("desc")){

                    order = SortBuilders.fieldSort("createTime").order(SortOrder.DESC);
                }else{

                    //升序
                    order= SortBuilders.fieldSort("createTime").order(SortOrder.ASC);
                }
            }


            Page<CallHistoryText> page = callHistoryTextBiz.queryCallHistoryPageList(builder,order,pageable,null);
            resultMap.put("msg","成功");
            resultMap.put("result",10000);
            resultMap.put("data",JSON.toJSONString(page));
            return resultMap;
        }catch (Exception e){
            logger.error("分页获取通话内容查询出错! data:{},错误信息:{}",paramMap,e);
            e.printStackTrace();
            resultMap.put("msg","失败");
            resultMap.put("result",10001);
        }
        return resultMap;
    }

    /**
     * 获取呼叫任务详情接口
     * @param callTaskId
     * @return
     */
    @Override
    public Map<String,Object> queryCallTaskDetailId(String callTaskId){
        Map<String,Object> resultMap = new HashMap<>();
        try {
            if(StringTools.isNotNull(callTaskId)){
                CallTaskDetail callTaskDetail = new CallTaskDetail();
                Object jsonStr = redisTemplate.opsForHash().get(RedisKey.CALL_TASK,callTaskId);
                if(StringTools.isNotempty(jsonStr)){
                    CallTaskDetailTotalVo callTaskDetailTotalVo = JSON.toJavaObject(JSON.parseObject(jsonStr.toString()),CallTaskDetailTotalVo.class);
                    BeanUtils.copyProperties(callTaskDetailTotalVo,callTaskDetail);
                }else {
                    callTaskDetail = callTaskDetailBiz.selectById(callTaskId);

                }
                resultMap.put("msg","成功");
                resultMap.put("result",10000);
                resultMap.put("data",JSON.toJSONString(callTaskDetail));
            }
        }catch (Exception e){
            logger.error("获取呼叫任务详情查询出错! callTaskId:{},错误信息:{}",callTaskId,e);
            e.printStackTrace();
            resultMap.put("msg","失败");
            resultMap.put("result",10001);
        }
        return resultMap;
    }

    /**
     * 呼叫任务完成操作
     * @param callTaskId
     */
    @Override
    public String callTaskCompletion(String callTaskId){
        if(!StringTools.isNotNull(callTaskId)){
            return "0";
        }
        try {
            redisTemplate.opsForHash().put(RedisKey.HAS_CALL_TASK_END,callTaskId,true);
        }catch (Exception e){
            logger.error("任务完成通知存入redis出错，callTaskId:{},错误信息：{}",callTaskId,e);
        }
        return "1";
    }


    /**
     * 根據map中的參數拼接查詢條件
     * @return
     */
    @Override
    public List<CallHistoryText> searchCallHistoryTextList(Map<String, Object> params) {

        List<CallHistoryText> callHistoryTexts = callHistoryTextBiz.searchCallHistoryTextList(params);

        return callHistoryTexts;
    }

    /**
     * 统计重播次数
     * @param params
     * @return
     */
    public String addCallReplayFrequency (Map<String, Object> params){
        WebResult result = new WebResult();
        if(params.containsKey("callTaskId")&&params.containsKey("replayFrequency")){
            try {
                callTaskDetailBiz.queueStatisticsCallHistory(params);
                result.setCode(GlobalStatic.CODE_1);
            } catch (Exception e) {
                result.setCode(GlobalStatic.CODE_0);
                result.setMsg(e.getMessage());
            }
        }
        return JSON.toJSONString(result);
    }

}
